
// <copyright file="AbstractDataRecord.cs" company="Subhadra Software Solutions">
//   
// </copyright>
// <summary>
//   The abstract data record.
// </summary>

namespace SubhadraSolutions.Sharp.Utils.Data.Common
{
    using System;
    using System.Collections.Generic;
    using System.Data;

    /// <summary>
    /// The abstract data record.
    /// </summary>
    public abstract class AbstractDataRecord : IDataRecord
    {
        #region Fields

        /// <summary>
        /// The ordinals dictionary.
        /// </summary>
        private Dictionary<string, int> ordinalsDictionary;

        #endregion Fields

        #region Constructors and Finalizers

        /// <summary>
        /// Initializes a new instance of the <see cref="AbstractDataRecord"/> class.
        /// </summary>
        protected AbstractDataRecord()
        {
            this.ColumnNames = new List<string>();
        }

        #endregion Constructors and Finalizers

        #region Public Properties

        /// <summary>
        /// Gets the field count.
        /// </summary>
        public int FieldCount
        {
            get
            {
                return this.ColumnNames.Count;
            }
        }

        #endregion Public Properties

        #region Properties

        /// <summary>
        /// Gets the column names.
        /// </summary>
        protected List<string> ColumnNames { get; private set; }

        #endregion Properties

        #region Public Indexers

        /// <summary>
        /// The this.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="object"/>.
        /// </returns>
        public abstract object this[int i] { get; }

        /// <summary>
        /// The this.
        /// </summary>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <returns>
        /// The <see cref="object"/>.
        /// </returns>
        public object this[string name]
        {
            get
            {
                int index = this.GetOrdinal(name);
                return this[index];
            }
        }

        #endregion Public Indexers

        #region Public Methods and Operators

        /// <summary>
        /// The get boolean.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public virtual bool GetBoolean(int i)
        {
            return this.getValue<bool>(i);
        }

        /// <summary>
        /// The get byte.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="byte"/>.
        /// </returns>
        public virtual byte GetByte(int i)
        {
            return this.getValue<byte>(i);
        }

        /// <summary>
        /// The get bytes.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="fieldOffset">
        /// The field offset.
        /// </param>
        /// <param name="buffer">
        /// The buffer.
        /// </param>
        /// <param name="bufferOffset">
        /// The bufferOffset.
        /// </param>
        /// <param name="length">
        /// The length.
        /// </param>
        /// <returns>
        /// The <see cref="long"/>.
        /// </returns>
        public virtual long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferOffset, int length)
        {
            return 0;
        }

        /// <summary>
        /// The get char.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="char"/>.
        /// </returns>
        public virtual char GetChar(int i)
        {
            return this.getValue<char>(i);
        }

        /// <summary>
        /// The get chars.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="fieldOffset">
        /// The fieldOffset.
        /// </param>
        /// <param name="buffer">
        /// The buffer.
        /// </param>
        /// <param name="bufferOffset">
        /// The bufferOffset.
        /// </param>
        /// <param name="length">
        /// The length.
        /// </param>
        /// <returns>
        /// The <see cref="long"/>.
        /// </returns>
        public virtual long GetChars(int i, long fieldOffset, char[] buffer, int bufferOffset, int length)
        {
            return 0;
        }

        /// <summary>
        /// The get data.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="IDataReader"/>.
        /// </returns>
        public virtual IDataReader GetData(int i)
        {
            return null;
        }

        /// <summary>
        /// The get data type name.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public virtual string GetDataTypeName(int i)
        {
            Type t = this.GetFieldType(i);
            if (t == null)
            {
                return null;
            }

            return t.ToString();
        }

        /// <summary>
        /// The get date time.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="DateTime"/>.
        /// </returns>
        public virtual DateTime GetDateTime(int i)
        {
            return this.getValue<DateTime>(i);
        }

        /// <summary>
        /// The get decimal.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="decimal"/>.
        /// </returns>
        public virtual decimal GetDecimal(int i)
        {
            return this.getValue<decimal>(i);
        }

        /// <summary>
        /// The get double.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="double"/>.
        /// </returns>
        public virtual double GetDouble(int i)
        {
            return this.getValue<double>(i);
        }

        /// <summary>
        /// The get field type.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="Type"/>.
        /// </returns>
        public virtual Type GetFieldType(int i)
        {
            return typeof(object);
        }

        /// <summary>
        /// The get float.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="float"/>.
        /// </returns>
        public virtual float GetFloat(int i)
        {
            return this.getValue<float>(i);
        }

        /// <summary>
        /// The get guid.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="Guid"/>.
        /// </returns>
        public virtual Guid GetGuid(int i)
        {
            return this.getValue<Guid>(i);
        }

        /// <summary>
        /// The get int 16.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="short"/>.
        /// </returns>
        public virtual short GetInt16(int i)
        {
            return this.getValue<short>(i);
        }

        /// <summary>
        /// The get int 32.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public virtual int GetInt32(int i)
        {
            return this.getValue<int>(i);
        }

        /// <summary>
        /// The get int 64.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="long"/>.
        /// </returns>
        public virtual long GetInt64(int i)
        {
            return this.getValue<long>(i);
        }

        /// <summary>
        /// The get name.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string GetName(int i)
        {
            return this.ColumnNames[i];
        }

        /// <summary>
        /// The get ordinal.
        /// </summary>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public int GetOrdinal(string name)
        {
            if (this.ordinalsDictionary == null)
            {
                this.ordinalsDictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
                for (int i = 0; i < this.ColumnNames.Count; i++)
                {
                    this.ordinalsDictionary.Add(this.ColumnNames[i], i);
                }
            }

            return this.ordinalsDictionary[name];
        }

        /// <summary>
        /// The get string.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public virtual string GetString(int i)
        {
            return (string)this[i];
        }

        /// <summary>
        /// The get value.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="object"/>.
        /// </returns>
        public object GetValue(int i)
        {
            return this[i];
        }

        /// <summary>
        /// The get values.
        /// </summary>
        /// <param name="values">
        /// The values.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public virtual int GetValues(object[] values)
        {
            for (int i = 0; i < this.FieldCount; i++)
            {
                values[i] = this[i];
            }

            return 0;
        }

        /// <summary>
        /// The is db null.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public virtual bool IsDBNull(int i)
        {
            if (this.GetFieldType(i).IsValueType)
            {
                return false;
            }

            return this[i] == null || this[i] == DBNull.Value;
        }

        #endregion Public Methods and Operators

        #region Methods

        /// <summary>
        /// The get value.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <typeparam name="T">
        /// </typeparam>
        /// <returns>
        /// The <see cref="T"/>.
        /// </returns>
        protected virtual T getValue<T>(int i)
        {
            return (T)this[i];
        }

        #endregion Methods
    }
}